-- AudioM
-- Create by panyl
-- 管理音效配置

module("AudioM", package.seeall);

-- 所有的道具信息
local audios = {};

-- 窗口的音效配置信息
local formAudios = {};

-- 格子材质对应音效
local coverFxs = {};

local curBgMusic = nil;
local curAudioId = nil;

-- 记录已播放过的音效
local cachedAudioEffects = {};

-- 检查间隔
local CHECK_INTERVAL = 5;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    -- 转换下audio信息表
    audios = {};
    local audio_CSV = get_audio_CSV();
    for i = 1, #audio_CSV do
        audios[audio_CSV[i].audio_id] = audio_CSV[i];
    end

    audio_CSV = {};

    -- 转换下form_audio信息表
    formAudios = {};
    local form_audio_CSV = get_form_audio_CSV();
    for i = 1, #form_audio_CSV do
        formAudios[form_audio_CSV[i].form_name] = form_audio_CSV[i];
    end

    form_audio_CSV = {};

    -- 转换下cover_audio信息表
    coverFxs = {};
    local cover_audio_CSV = get_cover_audio_CSV();
    for i = 1, #cover_audio_CSV do
        coverFxs[cover_audio_CSV[i].cover_res_name] = cover_audio_CSV[i].audio_id;
    end

    cover_audio_CSV = {};
end

-- 模块初始化
function init()
    loadCsv();

    -- 验证客户端不能走下面，不然会报错
    if isVerifyClient() then
        return;
    end

    if isAndroidPlatform() then
        local curFxVolume;
        if not UserDefaultM.getStringForKey("fx_volume")
            or UserDefaultM.getStringForKey("fx_volume") == "" then
            curFxVolume = 100;
        else
            curFxVolume = tonumber(UserDefaultM.getStringForKey("fx_volume"));
        end

        if curFxVolume ~= nil then
            AudioEngine.setEffectsVolume(curFxVolume / 100);
        end
    end
end

-- 检索音效信息
function query(audioId, path)
    local m = audios[audioId]

    if not m or path == "" or not path then
        return m
    end

    return m[path]
end

-- 检索窗口对应音效信息
function queryFormAudioInfo(formName, path)
    local m = formAudios[formName]

    if not m or path == "" or not path then
        return m
    end

    return m[path]
end

-- 检索格子材质音效
function queryCoverFx(coverPath)
    return coverFxs[coverPath] or "grid2";
end

-- 获取音效路径
function getPath(audioId)
    local type = query(audioId, "type");
    local src  = query(audioId, "audio_src");
    if not type or not src then
        return nil;
    end

    return string.format("audio/%s/%s.mp3", type, src);
end

-- 获取循环配置
function getLoop(audioId)
    return iif(query(audioId, "loop") == 1, true, false);
end

-- 播放背景音乐
function playBgMusic(audioId)
    -- 当前的音乐已经是这个，不再重新播放
    if curBgMusic == audioId then
        return;
    end

    if isVerifyClient() then
        -- 验证客户端走进来会导致报错，先屏蔽掉
        return;
    end

    -- 停掉老的背景音乐
    if curBgMusic ~= nil then
        stopPlayBgMusic(true);
    end

    curBgMusic = audioId;

    if isWindowsPlatform() then
        if LUA_COVERAGE == 1 then
            return;
        end

        local percent = tonumber(UserDefaultM.getStringForKey("bgm_volume"));
        if percent == nil then
            percent = 30;
        end
        curAudioId = ccexp.AudioEngine:play2d(AudioM.getPath(audioId), AudioM.getLoop(audioId), percent / 100);
    else
        local curBgVolume;
        if not UserDefaultM.getStringForKey("bgm_volume")
            or UserDefaultM.getStringForKey("bgm_volume") == "" then
            curBgVolume = 100;
        else
            curBgVolume = tonumber(UserDefaultM.getStringForKey("bgm_volume"));
        end

        if curBgVolume == 0 then
            return;
        end

        if isAndroidPlatform() then
            -- 在Android 5.0上，音乐循环有问题，改为定时检查是否重新播放
            local function doPlayMusic()
                AudioEngine.playMusic(AudioM.getPath(audioId), false);

                local isLoop = AudioM.getLoop(audioId);
                local duration = query(audioId, "duration");
                print("isLoop:"..tostring(isLoop)..",duration:"..tostring(duration));
                if isLoop and type(duration) == "number" and duration > 0 then

                    ScheduleM.createScheme("AudioM", function()
                            AudioEngine.playMusic(AudioM.getPath(audioId), false);
                        end, duration + 1, true);
                end
            end

            ScheduleM.deleteScheme("AudioM");
            doPlayMusic();
            AudioEngine.setMusicVolume(curBgVolume / 100);
        elseif isIosPlatform() then
            AudioEngine.playMusic(AudioM.getPath(audioId), AudioM.getLoop(audioId));
            setDefaultVolume();
        end
    end
end

-- 停止播放背景音乐
function stopPlayBgMusic(isReleaseData)
    if isVerifyClient() then
        -- 验证客户端走进来会导致报错，先屏蔽掉
        return;
    end

    if isWindowsPlatform() then
        ccexp.AudioEngine:stop(curAudioId);
    else
        AudioEngine.stopMusic(isReleaseData);
        curBgMusic = nil;
    end
end

-- 获取当前的背景音乐
function getCurBgMusic()
    return curBgMusic;
end

-- 设置默认音量
function setDefaultVolume()
    local percent;
    if not UserDefaultM.getStringForKey("bgm_volume")
        or UserDefaultM.getStringForKey("bgm_volume") == "" then
        percent = 100;
    else
        percent = tonumber(UserDefaultM.getStringForKey("bgm_volume"));
    end

    AudioEngine.setMusicVolume(percent / 100);
end

-- 设置音量
function setVolume(vol)
    if isVerifyClient() then
        -- 验证客户端走进来会导致报错，先屏蔽掉
        return;
    end

    if isWindowsPlatform() then
        if curAudioId then
            ccexp.AudioEngine:setVolume(curAudioId, vol);
        end
        return;
    end

    AudioEngine.setMusicVolume(vol);
end

-- 播放音效
local lastTime = os.time();
local fxCount = 0;

function playFx(audioId, isLoop)
    if LUA_COVERAGE == 1 then
        return;
    end

    if isVerifyClient() then
        -- 验证客户端走进来会导致报错，先屏蔽掉
        return;
    end

    Profiler.funcBegin("playFx");

    local curFxVolume;
    if not UserDefaultM.getStringForKey("fx_volume")
        or UserDefaultM.getStringForKey("fx_volume") == "" then
        curFxVolume = 100;
    else
        curFxVolume = tonumber(UserDefaultM.getStringForKey("fx_volume"));
    end

    if curFxVolume == 0 then
        return;
    end

    local fx = nil;

    -- 播放音效
    if not isLoop then
        isLoop = false;
    end

    local path = AudioM.getPath(audioId);
    if path == nil then
        cclog("### 音效(%s)不存在。", audioId);
        return;
    end

    -- 同一秒内，最多只允许3个音效启动播放
    if os.time() ~= lastTime then
        fxCount = 1;
    else
        fxCount = fxCount + 1;
        if fxCount > 3 then
            -- 超过3个，直接忽略
            return;
        end
    end

    lastTime = os.time();

    if isWindowsPlatform() then
        fx = ccexp.AudioEngine:play2d(path, isLoop, curFxVolume / 100);
    else
        fx = AudioEngine.playEffect(path, isLoop);
    end

    cachedAudioEffects[path] = 1;

    Profiler.funcEnd("playFx");

    return fx;
end

-- 停止音效
function stopFx(handle)
    if isVerifyClient() then
        -- 验证客户端走进来会导致报错，先屏蔽掉
        return;
    end

    if not isWindowsPlatform() then
        AudioEngine.stopEffect(handle);
    else
        ccexp.AudioEngine:stop(handle);
    end
end

-- 卸载音效缓存
function purge()
    if isVerifyClient() then
        -- 验证客户端走进来会导致报错，先屏蔽掉
        return;
    end

    if not isWindowsPlatform() then
        for path, _ in pairs(cachedAudioEffects) do
            AudioEngine.unloadEffect(path);
        end
    end
end

